static uint64_t g_mcg_cap;
+/* Real value in physical CTL MSR */
+static uint64_t h_mcg_ctl = 0UL;
+static uint64_t *h_mci_ctrl;
+int firstbank;
+
static void intpose_init(void);
static void mcinfo_clear(struct mc_info *);
break;
}
+ if ( !h_mci_ctrl )
+ {
+ h_mci_ctrl = xmalloc_array(uint64_t, nr_mce_banks);
+ if (!h_mci_ctrl)
+ {
+ dprintk(XENLOG_INFO, "Failed to alloc h_mci_ctrl\n");
+ return;
+ }
+ /* Don't care banks before firstbank */
+ memset(h_mci_ctrl, 0xff, sizeof(h_mci_ctrl));
+ for (i = firstbank; i < nr_mce_banks; i++)
+ rdmsrl(MSR_IA32_MC0_CTL + 4*i, h_mci_ctrl[i]);
+ }
+ if (g_mcg_cap & MCG_CTL_P)
+ rdmsrl(MSR_IA32_MCG_CTL, h_mcg_ctl);
set_poll_bankmask(c);
if (!inited)
printk(XENLOG_INFO "CPU%i: No machine check initialization\n",
*val);
break;
case MSR_IA32_MCG_CTL:
- *val = d->arch.vmca_msrs.mcg_ctl;
+ /* Always 0 if no CTL support */
+ *val = d->arch.vmca_msrs.mcg_ctl & h_mcg_ctl;
mce_printk(MCE_VERBOSE, "MCE: rdmsr MCG_CTL 0x%"PRIx64"\n",
*val);
break;
switch (msr & (MSR_IA32_MC0_CTL | 3))
{
case MSR_IA32_MC0_CTL:
- *val = d->arch.vmca_msrs.mci_ctl[bank];
+ *val = d->arch.vmca_msrs.mci_ctl[bank] &
+ (h_mci_ctrl ? h_mci_ctrl[bank] : ~0UL);
mce_printk(MCE_VERBOSE, "MCE: rdmsr MC%u_CTL 0x%"PRIx64"\n",
bank, *val);
break;
switch ( msr )
{
case MSR_IA32_MCG_CTL:
- if ( val && (val + 1) )
- {
- mce_printk(MCE_QUIET, "MCE: val \"%"PRIx64"\" written "
- "to MCG_CTL should be all 0s or 1s\n", val);
- ret = -1;
- break;
- }
d->arch.vmca_msrs.mcg_ctl = val;
break;
case MSR_IA32_MCG_STATUS:
switch ( msr & (MSR_IA32_MC0_CTL | 3) )
{
case MSR_IA32_MC0_CTL:
- if ( val && (val + 1) )
- {
- mce_printk(MCE_QUIET, "MCE: val written to MC%u_CTL "
- "should be all 0s or 1s (is %"PRIx64")\n",
- bank, val);
- ret = -1;
- break;
- }
d->arch.vmca_msrs.mci_ctl[bank] = val;
break;
case MSR_IA32_MC0_STATUS:
(r) <= MSR_IA32_MC0_MISC + (nr_mce_banks - 1) * 4 && \
((r) - MSR_IA32_MC0_CTL) % 4 != 0) /* excludes MCi_CTL */
+int mca_ctl_conflict(struct mcinfo_bank *bank, struct domain *d)
+{
+ int bank_nr;
+
+ if ( !bank || !d || !h_mci_ctrl )
+ return 1;
+
+ /* Will MCE happen in host if If host mcg_ctl is 0? */
+ if ( ~d->arch.vmca_msrs.mcg_ctl & h_mcg_ctl )
+ return 1;
+
+ bank_nr = bank->mc_bank;
+ if (~d->arch.vmca_msrs.mci_ctl[bank_nr] & h_mci_ctrl[bank_nr] )
+ return 1;
+ return 0;
+}
+
static int x86_mc_msrinject_verify(struct xen_mc_msrinject *mci)
{
struct cpuinfo_x86 *c;
int ser_support = 0;
static int nr_intel_ext_msrs = 0;
-static int firstbank;
/* Below are for MCE handling */
struct mce_softirq_barrier {
* the mfn in question) */
BUG_ON( result->owner == DOMID_COW );
if ( result->owner != DOMID_XEN ) {
+
d = get_domain_by_id(result->owner);
+ if ( mca_ctl_conflict(bank, d) )
+ {
+ /* Guest has different MCE ctl with hypervisor */
+ put_domain(d);
+ return;
+ }
+
gfn =
mfn_to_gmfn(d, ((bank->mc_addr) >> PAGE_SHIFT));
bank->mc_addr =